package com.atguigu.srb.mq.config;

import com.atguigu.srb.mq.consts.MqConsts;
import lombok.extern.slf4j.Slf4j;
import org.springframework.amqp.core.*;
import org.springframework.amqp.rabbit.connection.CorrelationData;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.support.converter.Jackson2JsonMessageConverter;
import org.springframework.amqp.support.converter.MessageConverter;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.lang.Nullable;

import javax.annotation.PostConstruct;
import javax.annotation.Resource;

@Configuration
@Slf4j
public class MqConfig  {
    //配置生产者回调的方法
//    @Resource
//    RabbitTemplate rabbitTemplate;

//    @PostConstruct
//    public void init(){
//
//    }


    //将springamqp包中提供的 可以将对象转为json字符串的转换器注入到容器中
    @Bean
    public MessageConverter messageConverter(){
        return new Jackson2JsonMessageConverter();
    }

    //死信交换机
    @Bean
    public Exchange deadExchange(){
        return ExchangeBuilder.topicExchange("dead.exchange")
                .durable(true)
                .ignoreDeclarationExceptions()
                .build();
    }
    //死信队列
    @Bean
    public Queue deadQueue(){
        return QueueBuilder.durable("dead.queue")
                .build();
    }
    //死信队列绑定死信交换机
    @Bean
    public Binding deadBinding(Exchange deadExchange,Queue deadQueue){
        return BindingBuilder.bind(deadQueue)
                .to(deadExchange)
                .with("dead.msg")
                .noargs();
    }
    //消息变为死信：当业务队列绑定了死信队列，它的消息被丢弃时(basicNAck-false basicReject-false)
    //             当业务队列设置了过期时间时，一个消息超过过期时间未被消费 会变成死信
    //             mq的队列有最大大小和队列长度， 只要任意一个阈值达到了，不能存入队列中的消息会变成死信
    //业务交换机
    @Bean
    public Exchange smsExchange(){
        return ExchangeBuilder.topicExchange(MqConsts.EXCHANGE_TOPIC_SMS)
                .durable(true)
                .ignoreDeclarationExceptions()
                .build();
    }
    //业务队列：绑定死信队列
    @Bean
    public Queue smsQueue(){
        return QueueBuilder.durable(MqConsts.QUEUE_SMS_ITEM)
                .deadLetterExchange("dead.exchange")//死信交换机
                .deadLetterRoutingKey("dead.msg")//sms队列中的消息变成死信时 会自动交给死信交换机使用死信路由key进行路由
                .build();
    }
    //业务队列交换机绑定
    @Bean
    public Binding smsBinding(Exchange smsExchange,Queue smsQueue){
        return BindingBuilder.bind(smsQueue)
                .to(smsExchange)
                .with(MqConsts.ROUTING_SMS_ITEM)
                .noargs();
    }


//    @Override
//    public void afterPropertiesSet() throws Exception {
//        //消息未达到队列的回调
//        rabbitTemplate.setReturnCallback((Message message, int replyCode, String replyText, String exchange, String routingKey)->{
//            //消息未达到队列
//            log.error("消息未到达队列....");
//        });
//        //消息是否达到交换机的回调
//        rabbitTemplate.setConfirmCallback((CorrelationData correlationData, boolean ack, String cause)->{
//            if(!ack){
//                //消息未达到交换机
//                log.error("消息未达到交换机....");
//            }
//        });
//    }
}
